package youleche.com.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import youleche.com.factory.MLLogFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import net.sf.json.JSONObject;

/**
 * json处理类
 * @author shenyuc629
 *
 */
public class JsonHelper {
	/**
	 * @see 把json对象以json格式的数据输出到页面
	 * @param Object obj 是一个对象形式，类似User
	 */
	public static void printObjectToJsonString(HttpServletResponse response, Object obj){
		response.setCharacterEncoding("UTF-8");
		try {
			response.getWriter().print(net.sf.json.JSONObject.fromObject(obj).toString());
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	/**
	 * @see 把josn集合json格式的数据输出到页面(Gson)
	 * @param Object objList 是一个集合形式，类似List<Object>(Gson)
	 */
	public static void printListToJsonString(HttpServletResponse response,Object objList){
		response.setCharacterEncoding("UTF-8");
		Gson gson = new Gson();
		String json = gson.toJson(objList);
		try {
			response.getWriter().print(json);
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	/**
	 * @see 把josn集合json格式的数据输出到页面
	 * @param Object objList 是一个集合形式，类似List<Object>
	 */
	public static void printObjectListToJsonString(HttpServletResponse response,Object objList){
		response.setCharacterEncoding("UTF-8");
		net.sf.json.JSONObject jo = new net.sf.json.JSONObject();
		jo.put("list", objList);
		try {
			response.getWriter().print(jo);
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	/**
	 * @see 把josn集合json格式的数据输出到页面(针对easyUI的可编辑table控件)
	 * @param Object objList 是一个集合形式，类似List<Object>
	 */
	public static void printObjectListToJsonStringForEasyUI(HttpServletResponse response,@SuppressWarnings("rawtypes") List list){
		response.setCharacterEncoding("UTF-8");
		net.sf.json.JSONObject jo = new net.sf.json.JSONObject();
		jo.put("rows", list);
		jo.put("total", list.size());
		try {
			response.getWriter().print(jo);
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	/**
	 * 读取json键值对(不能有重复键)
	 * @param request 请求
	 * @return
	 */
	public static Map<String, String> readJsonKeyValues(HttpServletRequest request){
		String jsonString = readJSONString(request);
		Map<String, String> map = new HashMap<String, String>();
		String[] keyValueArr = jsonString.split(",");
		for (String keyValue : keyValueArr) {
			Pattern pattern = Pattern.compile("\"(.*?)\"");
			Matcher matcher = pattern.matcher(keyValue);
			int index = 1;
			String key = "";
			String value = "";
			while(matcher.find()){
				if(index == 1){
					key = matcher.group(1);
				}else{
					value = matcher.group(1);
				}	
				
				index++;
			}
			
			map.put(key, value);
		}
		
		return map;
	}
	
	/**
	 * 读取json键值对(不能有重复键)
	 * @param jsonString Json字符串
	 * @return
	 */
	public static Map<String, String> readJsonKeyValues(String jsonString){
		Map<String, String> map = new HashMap<String, String>();
		String[] keyValueArr = jsonString.split(",");
		for (String keyValue : keyValueArr) {
			Pattern pattern = Pattern.compile("\"(.*?)\"");
			Matcher matcher = pattern.matcher(keyValue);
			int index = 1;
			String key = "";
			String value = "";
			while(matcher.find()){
				if(index == 1){
					key = matcher.group(1);
				}else{
					value = matcher.group(1);
				}	
				
				index++;
			}
			
			map.put(key, value);
		}
		
		return map;
	}

	/**
	 * 从request中读取字符串对象并且返回对象的json字符串
	 * @param request
	 * @return
	 */
	public static String readJSONString(HttpServletRequest request){
		StringBuffer json = new StringBuffer();
		String line = null;
		try {
			BufferedReader reader = request.getReader();
			while((line = reader.readLine()) != null) {
				json.append(line);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		return json.toString();
	}
	
	/**
	 * 从request中读取json对象
	 * @param request
	 * @return JSONObject
	 */
	public static JSONObject readJSONObject(HttpServletRequest request){
		return JSONObject.fromObject(readJSONString(request));
	}
	
	/**
	 * 从request流中获取对象（该流中是一个json字符串）
	 * @param request 请求对象
	 * @param clazz Object.class
	 * @return 返回对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws ParseException 
	 */
	public static Object getObjectByJsonString(HttpServletRequest request, Class<?> clazz ) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException, ParseException{
		return getObjectByJsonString(readJsonKeyValues(request), clazz);
	}
	
	/**
	 * 从request流中获取对象（该流中是一个json字符串）(GSON)
	 * @param request 请求对象
	 * @param clazz Object.class
	 * @return 返回对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws ParseException 
	 */
	public static Object getObjectByJsonStringAndDateFormat(HttpServletRequest request, Class<?> clazz, String dateFormat ) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException, ParseException{
		
		String readJsonString = readJSONString(request);
		Gson gson=  new GsonBuilder().setDateFormat(dateFormat).create();
		return gson.fromJson(readJsonString, clazz);
	}
	
	/**
	 * 获取json字符串里面的对象（Gson）
	 * @param request request请求对象
	 * @param clazz 需要获取的对象
	 * @return 返回对象
	 */
	public static Object getObjectByJsonStringAndGson(HttpServletRequest request, Class<?> clazz){
		String readJsonString = readJSONString(request);
		Gson gson = new Gson();
		return gson.fromJson(readJsonString, clazz);
	}
	
	/**
	 * 把json字符串转换为对象
	 * @param json json字符串
	 * @param clazz 类
	 * @return 返回对象
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws ParseException 
	 */
	private static Object getObjectByJsonString(Map<String, String> keyValue, Class<?> clazz) throws InstantiationException, IllegalAccessException, IntrospectionException, IllegalArgumentException, InvocationTargetException, ParseException{;
		Set<Map.Entry<String, String>> set = keyValue.entrySet();
		Field[] fields = clazz.getDeclaredFields();
		Object obj = clazz.newInstance();
		for (Field field : fields) {
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
			Method setMethod = pd.getWriteMethod();
			for (Iterator<Map.Entry<String, String>>  it = set.iterator(); it.hasNext();) {
				Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
				if(entry.getKey().equals(field.getName())){
					if(setMethod.getName().toUpperCase().equals("SET" + entry.getKey().toUpperCase())){						
						Class<?>[] paramTypes = setMethod.getParameterTypes();
						if(paramTypes[0].getName() == String.class.getName()){
							setMethod.invoke(obj, entry.getValue());
						}else if(paramTypes[0].getName() == Date.class.getName()){
							setMethod.invoke(obj, new SimpleDateFormat("yyyy-MM-dd").parse(entry.getValue()));
						}else if(paramTypes[0].getName() == Integer.class.getName()){
							setMethod.invoke(obj, Integer.parseInt(entry.getValue()));
						}						
					}
					
					break;
				}else{
					continue;
				}	
			}
		}
		
		return obj;
	}
}
